/**
 * Proxy 代理
*/

const { time } = require("console");

/**
 * demo
 * author： sunze
 * 实现私有属性
*/
const obj = {
  name: '鸣人',
  _tag: '螺旋丸'
}

const handler = {
  get:(target, key, proxy) => {
    if(key.startsWith('_')) {
      console.log(`${key} is private variables!`)
      return null;
    }
    return target[key]
  },
  set:(target, key, value, proxy) => {
    if(key.startsWith('_')) {
      console.log(`can't modify private variables: ${key}`);
      return null;
    }
    return Reflect.set(target, key, value, proxy);
  }
}

const objProxy = new Proxy(obj, handler);

// objProxy._tag = '_tag';  //can't modify private variables: _tag


/**
 * demo
 * author: sunze
 * proxy 拦截数据并对格式进行校验
 * 可对类的校验规则进行拓展
*/
class Person {
  constructor(arg) {
    //入参必须是对象
    if(Object.prototype.toString.call(arg) !== '[object Object]') {
      throw Error('Person constructor param is not Object!');
    } else {
      Object.assign(this, arg)
    }

    return this.createValidator(this);
  }

  validator = {}

  createValidator(target) {
    return new Proxy(target, {
        _validator: this.validator,
        set:(target, key, value, proxy) => {
            if (target.hasOwnProperty(key)) {
                let validator = this._validator[key];
                if (!!validator(value)) {
                    return Reflect.set(target, key, value, proxy);
                } else {
                    throw Error(`Cannot set ${key} to ${value}. Invalid.`);
                }
            } else {
                throw Error(`${key} is not a valid property`)
            }
        }
    });
  }

  updateValidator(arg) {
    if(Object.prototype.toString.call(arg) !== '[object Object]') {
      throw Error('Person constructor param is not Object!');
    } else {
      Object.assign(this.validator, arg)
    }
  }
}

const validators = {
  name(val) {
    return typeof val === 'string';
  },
  age(val) {
      return typeof age === 'number' && age > 18;
  }
}

const personObj = new Person({name: 'li'})

// personObj.updateValidator(validators);

// personObj.name = 33;   //Cannot set name to 33. Invalid.
// personObj.age = '23';  //Error: age is not a valid property

// console.log(personObj)

/**
 * demo
 * author： sunze
 * 日志记录
*/
const apis = {
  _id: 'hash(123abc456)',
  login: (params) => {/**  login */ console.log(params)},
  getList: (params) => {/**  getList */},
  getUserInfo: (params) => {/**  getList */},
}

function logMeth(timeStamp, method) {
  setTimeout(() => {
    console.log(`${timeStamp} - logging ${method} request!`)
  },0)
}

const logsHandler = {
  get:(target, key, proxy) => {
    let value = target[key];
    return (...arg) => {
      logMeth(new Date(), key);
      return Reflect.apply(value, target, arg);
    }
  }
}

const apisProxy = new Proxy(apis, logsHandler);

// apisProxy.login({username: '鸣人', password: '123456'});
